package com.symaster.common.swing.element;

import com.symaster.common.swing.entity.MessageItem;
import com.symaster.common.swing.util.SwingUtil;

import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.plaf.BorderUIResource;
import java.awt.*;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author yinmiao
 * @date 2021-10-08 10:16
 */
public class ConsolePanel extends JPanel implements com.symaster.common.ConsolePanel {

    public static final int OUT = 0;
    public static final int ERR = 1;
    private static final int lineHeight = 20;
    private static final BorderUIResource.BevelBorderUIResource border1 = new BorderUIResource.BevelBorderUIResource(1);
    private static final BorderUIResource.BevelBorderUIResource border0 = new BorderUIResource.BevelBorderUIResource(0);
    private static final ImageIcon clean = SwingUtil.loadIconEnabledCache("delete.png", 20, 20);
    private static final ImageIcon toBottom = SwingUtil.loadIconEnabledCache("down_to_bottom.png", 20, 20);
    private static Integer maxItemWidth;
    public Integer maxRow = 5000;
    private Boolean autoToBottom;
    private JPanel root_panel;
    private JButton down_to_bottom_button;
    private JButton clean_console_button;
    private JTextArea console_text_area;
    private JScrollPane root_text_area_scroll_panel;
    private JPanel center_flow_layout;
    private JPanel root_center;
    private Color background;
    private Color panelBackground;
    private Color fontColor;
    private Color errorFontColor;
    private Color warningFontColor;

    public ConsolePanel() {
        initUIManager();
        setLayout(new BorderLayout());
        add(root_panel, BorderLayout.CENTER);
        initPage();
        initIcon();
        initListener();
        initData();
    }

    public static void main(String[] args) throws InterruptedException {
        JFrame jFrame = new JFrame();
        ConsolePanel consolePanel = new ConsolePanel();
        consolePanel.maxRow = 500;
        jFrame.setContentPane(consolePanel);
        jFrame.setPreferredSize(new Dimension(400, 700));
        jFrame.pack();
        SwingUtil.toCenter(jFrame);
        jFrame.setVisible(true);

        while (true) {
            consolePanel.print(UUID.randomUUID().toString());
            TimeUnit.MILLISECONDS.sleep(5);
        }
    }

    private void initPage() {
        root_text_area_scroll_panel.getVerticalScrollBar().setUnitIncrement(20);
        center_flow_layout.setBackground(background);
    }

    private void initUIManager() {
        background = UIManager.getColor("ConsolePanel.background");
        panelBackground = UIManager.getColor("ConsolePanel.panelBackground");
        fontColor = UIManager.getColor("ConsolePanel.fontColor");
        errorFontColor = UIManager.getColor("ConsolePanel.errorFontColor");
        warningFontColor = UIManager.getColor("ConsolePanel.warningFontColor");
        if (background == null) {
            background = new Color(255, 255, 255);
            UIManager.put("ConsolePanel.background", background);
        }
        if (panelBackground == null) {
            panelBackground = new Color(242, 242, 242);
            UIManager.put("ConsolePanel.panelBackground", panelBackground);
        }
        if (fontColor == null) {
            fontColor = new Color(0, 0, 0);
            UIManager.put("ConsolePanel.fontColor", fontColor);
        }
        if (errorFontColor == null) {
            errorFontColor = new Color(245, 108, 108);
            UIManager.put("ConsolePanel.errorFontColor", errorFontColor);
        }
        if (warningFontColor == null) {
            warningFontColor = new Color(230, 162, 60);
            UIManager.put("ConsolePanel.warningFontColor", warningFontColor);
        }
    }

    public void print(String str, int type) {
        SwingUtilities.invokeLater(() -> {
            MessageItem messageItem1 = new MessageItem(str, type, lineHeight);
            center_flow_layout.add(messageItem1);
            if (maxItemWidth == null || messageItem1.getItemWidth() > maxItemWidth) {
                maxItemWidth = messageItem1.getItemWidth();
            }
            if (center_flow_layout.getComponentCount() > maxRow) {
                center_flow_layout.remove(0);
            }
            reCenterFlowLayoutSize();
        });
    }

    @Override
    public void debug(String str, Object... args) {

    }

    @Override
    public void debug(String message) {

    }

    @Override
    public JPanel getRootPanel() {
        return root_panel;
    }

    @Override
    public void printlnErr(String message) {
        print(message, ERR);
    }

    @Override
    public void printErr(String message) {
        print(message, ERR);
    }

    @Override
    public void println(String str) {
        print(str, OUT);
    }

    @Override
    public void print(String message) {
        print(message, OUT);
    }

    @Override
    public void printf(String format, Object... args) {
        print(String.format(format, args));
    }

    @Override
    public void printfErr(String str, Object... args) {
        print(String.format(str, args), ERR);
    }

    private void initData() {
        startRoll();
    }

    private void toBottom() {
        JScrollBar verticalScrollBar = root_text_area_scroll_panel.getVerticalScrollBar();
        verticalScrollBar.setValue(verticalScrollBar.getMaximum());
    }

    private void reCenterFlowLayoutSize() {
        Rectangle viewportBorderBounds = root_text_area_scroll_panel.getViewportBorderBounds();
        int width = (int) viewportBorderBounds.getWidth();
        int height = (int) viewportBorderBounds.getHeight();

        if (center_flow_layout.getComponentCount() > 1) {
            height = Math.max(height, center_flow_layout.getComponentCount() * lineHeight);
        }

        Dimension dimension;
        if (maxItemWidth != null) {
            dimension = new Dimension(Math.max(width, maxItemWidth), height);
        } else {
            dimension = new Dimension(width, height);
        }

        center_flow_layout.setPreferredSize(dimension);
        if (root_text_area_scroll_panel != null) {
            root_text_area_scroll_panel.updateUI();
        }
    }

    private void startRoll() {
        autoToBottom = true;
        down_to_bottom_button.setBorder(border1);
    }

    private void stopRoll() {
        autoToBottom = false;
        down_to_bottom_button.setBorder(border0);
    }

    private void initListener() {
        clean_console_button.addActionListener((e) -> {
            maxItemWidth = 0;
            center_flow_layout.removeAll();
            reCenterFlowLayoutSize();
        });
        down_to_bottom_button.addActionListener((e) -> {
            if (autoToBottom == null || autoToBottom) {
                stopRoll();
            } else {
                startRoll();
            }
        });
        root_text_area_scroll_panel.addComponentListener(new ComponentListener() {
            @Override
            public void componentResized(ComponentEvent e) {
                reCenterFlowLayoutSize();
            }

            @Override
            public void componentMoved(ComponentEvent e) {

            }

            @Override
            public void componentShown(ComponentEvent e) {

            }

            @Override
            public void componentHidden(ComponentEvent e) {

            }
        });
        center_flow_layout.addComponentListener(new ComponentListener() {
            @Override
            public void componentResized(ComponentEvent e) {
                if (autoToBottom != null && autoToBottom && center_flow_layout.getComponents() != null && center_flow_layout.getComponents().length > 1) {
                    toBottom();
                }
            }

            @Override
            public void componentMoved(ComponentEvent e) {

            }

            @Override
            public void componentShown(ComponentEvent e) {

            }

            @Override
            public void componentHidden(ComponentEvent e) {

            }
        });
    }

    private void initIcon() {
        down_to_bottom_button.setIcon(toBottom);
        clean_console_button.setIcon(clean);
    }

    {
        // GUI initializer generated by IntelliJ IDEA GUI Designer
        // >>> IMPORTANT!! <<<
        // DO NOT EDIT OR ADD ANY CODE HERE!
        $$$setupUI$$$();
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        root_panel = new JPanel();
        root_panel.setLayout(new BorderLayout(0, 0));
        root_panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
        final JPanel panel1 = new JPanel();
        panel1.setLayout(new FlowLayout(FlowLayout.CENTER, 2, 5));
        panel1.setPreferredSize(new Dimension(30, 0));
        root_panel.add(panel1, BorderLayout.EAST);
        panel1.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
        down_to_bottom_button = new JButton();
        down_to_bottom_button.setFocusPainted(false);
        down_to_bottom_button.setMaximumSize(new Dimension(20, 20));
        down_to_bottom_button.setMinimumSize(new Dimension(20, 20));
        down_to_bottom_button.setPreferredSize(new Dimension(20, 20));
        down_to_bottom_button.setText("");
        panel1.add(down_to_bottom_button);
        clean_console_button = new JButton();
        clean_console_button.setFocusPainted(false);
        clean_console_button.setMaximumSize(new Dimension(20, 20));
        clean_console_button.setMinimumSize(new Dimension(20, 20));
        clean_console_button.setPreferredSize(new Dimension(20, 20));
        clean_console_button.setText("");
        panel1.add(clean_console_button);
        console_text_area = new JTextArea();
        console_text_area.setBackground(new Color(-14407378));
        console_text_area.setCaretColor(new Color(-425364));
        console_text_area.setDisabledTextColor(new Color(-9800835));
        console_text_area.setEditable(false);
        console_text_area.setForeground(new Color(-6447198));
        console_text_area.setVisible(false);
        panel1.add(console_text_area);
        root_center = new JPanel();
        root_center.setLayout(new BorderLayout(0, 0));
        root_panel.add(root_center, BorderLayout.CENTER);
        root_center.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
        root_text_area_scroll_panel = new JScrollPane();
        root_center.add(root_text_area_scroll_panel, BorderLayout.CENTER);
        root_text_area_scroll_panel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
        center_flow_layout = new JPanel();
        center_flow_layout.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 0));
        root_text_area_scroll_panel.setViewportView(center_flow_layout);
        center_flow_layout.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
    }

    /** @noinspection ALL */
    public JComponent $$$getRootComponent$$$() {
        return root_panel;
    }

    private static class PrintEntity {
        private String message;
        private Integer type;
    }

}
